﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace SharePointRsync
{
    class RSyncEventHandler : SPItemEventReceiver
    {
        //Sync Item CType
        private string[] contenttypes = new string[] { "0x01009C703949A1AE054580E048B68B70E934" };

        public override void ItemUpdating(SPItemEventProperties properties)
        {
            try
            {
                this.EventFiringEnabled = false;

                if (ShouldContinueProcessingEvent(properties))
                {
                    CheckIfFileNameIsChanged(properties);
                }
            }
            catch (Exception ex)
            {
                LogError(ex);
            }
            finally
            {
                this.EventFiringEnabled = true;
            }
        }

        public override void ItemDeleting(SPItemEventProperties properties)
        {
            try
            {
                this.EventFiringEnabled = false;

                if (ShouldContinueProcessingEvent(properties))
                {
                    DeleteItemFromDestination(properties);
                }
            }
            catch (Exception ex)
            {
                LogError(ex);
            }
            finally
            {
                this.EventFiringEnabled = true;
            }
        }

        private void DeleteItemFromDestination(SPItemEventProperties properties)
        {
            try
            {
                string syncTo = GetSyncPath((string)properties.ListItem["SyncTo"]);
                string syncFrom = GetSyncPath((string)properties.ListItem["SyncFrom"]);
                string fileName = Path.GetFileName(syncFrom);

                if (!string.IsNullOrEmpty(syncFrom))
                {
                    if (fileName.IndexOf('.') != -1)
                    {
                        SPSecurity.RunWithElevatedPrivileges(delegate()
                        {
                            FileInfo destinationFile = new FileInfo(syncTo + fileName);
                            destinationFile.Delete();
                        });
                    }
                    else if (properties.ListItem["CreateZip"].ToString().CompareTo("Yes") == 0)
                    {
                        fileName = (string)properties.ListItem.Title + ".zip";
                        SPSecurity.RunWithElevatedPrivileges(delegate()
                        {
                            FileInfo destinationFile = new FileInfo(syncTo + fileName);
                            destinationFile.Delete();
                        });
                    }
                    else
                    {
                        SPSecurity.RunWithElevatedPrivileges(delegate()
                        {
                            DirectoryInfo destinationDirectory = new DirectoryInfo(syncTo);
                            destinationDirectory.Delete(true);
                        });
                    }
                    properties.ListItem["SyncLog"] = (string)properties.ListItem["SyncLog"] + "\n\nItems changed name or path and were removed from " + syncTo + "\n";
                }
            }
            catch (Exception ex)
            {
                LogError(ex);
                properties.ListItem["SyncLog"] = (string)properties.ListItem["SyncLog"] + "\n\nAn error occured when trying to remove your file(s) from the destination. You will have to remove the old destination file manually\n";
            }
        }

        private void CheckIfFileNameIsChanged(SPItemEventProperties properties)
        {
            if (((string)properties.ListItem["SyncFrom"] != (string)properties.AfterProperties["SyncFrom"]))
            {
                DeleteItemFromDestination(properties);
            }
            else if ((properties.ListItem.Title != (string)properties.AfterProperties["Title"]) && (properties.ListItem["CreateZip"].ToString().CompareTo("Yes") == 0))
            {
                DeleteItemFromDestination(properties);
            }
        }

        private string GetSyncPath(string path)
        {
            string syncPath = new SPFieldUrlValue(path).Url.Replace("%20", " ");

            if (syncPath.IndexOf('.') == -1)
            {
                if (syncPath.EndsWith("/") == false)
                    syncPath = syncPath + "/";
            }
            if (syncPath.StartsWith("\\\\\\\\"))
                syncPath = syncPath.Replace("\\\\\\\\", "\\\\");
            return syncPath.Remove(0, 5).Replace("/", "\\");
        }

        private bool ShouldContinueProcessingEvent(SPItemEventProperties properties)
        {
            //no system or workflow events
            if (properties.UserLoginName.ToLower() == "mathworks\\spadmin" || properties.UserLoginName.ToLower() == "sharepoint\\system")
            {
                return false;
            }
            //skip check-in since event will fire again for update
            if (properties.AfterProperties["vti_sourcecontrolcheckedoutby"] == null && properties.BeforeProperties["vti_sourcecontrolcheckedoutby"] != null)
            {
                return false;
            }
            //is sync item
            if (contenttypes.Any(s => ((SPContentTypeId)properties.ListItem["ContentTypeId"]).Parent.ToString() == s))
            {
                return true;
            }
            return false;
        }

        private static void LogError(Exception ex)
        {
            SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory("RFAINEventReceiver",
                                            TraceSeverity.Unexpected, EventSeverity.Error),
                                            TraceSeverity.Unexpected,
                                            ex.Message,
                                            ex.StackTrace);
        }
    }
}
